/*
* @Date: 2020/4/28
* @Author: XueChengwu <xuechengwu@erayt.com>
* @Copyright: 2015-2019 Erayt, Inc.
* @Description: If you have some questions, please contact: xuechengwu@erayt.com.
*/
import React from 'react';
import $ from 'jquery';
import { Modal } from 'antd';
import ReactDOM from 'react-dom';

// 下划线转换驼峰
function toHump(name) {
  return name.replace(/\_(\w)/g, function(all, letter){
    return letter.toUpperCase();
  });
}
// 驼峰转换下划线
function toLine(name) {
  return name.replace(/([A-Z])/g,"_$1").toLowerCase();
}

window.XUE = {
  getGuid() {
    const target = 'xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx';
    return target.replace(/[x]/g, (c) => {
      const r = Math.random() * 16 | 0,
        v = c === 'x' ? r : (r & 0x3 | 0x8);
      return v.toString(16);
    });
  },
  toHump,
  toLine,
  showDialog({title, onOk, onCancel}, content) {
    let div = document.createDocumentFragment();
    document.body.append(div);
    const modal = (
      <Modal
        title={title}
        visible
        closable
        onOk={onOk}
        onCancel={onCancel}
      >
        { content }
      </Modal>
    );
    ReactDOM.render(modal, div);
    return {
      modal,
      close() {
        ReactDOM.render(<React.Fragment></React.Fragment>, div);
      }
    };
  },
  codeGenerator(
    {
      components = [],
      functions = [],
      datas = {},
      styles,
      renderSource,
    }) {
    const { states = [], props = [] } = datas;
    let code = `import React from React;\nimport { ${components.join(',')} } from 'antd';\n`;
    // TODO: 生产style代码
    code += `export default class extends React.Component {\n\tconstructor(props) {\n\t\tsuper(props);\n\t\tthis.state = {\n\t\t\t`;
    for (let i = 0; i < states.length; i++) {
      if (states[i].type === 'string') {
        code += `${states[i].name}: '${states[i].value}',\n\t\t\t`;
      } else if (states[i].type === 'bool') {
        code += `${states[i].name}: ${states[i].value},\n\t\t\t`;
      } else if (states[i].type === 'number') {
        code += `${states[i].name}: ${states[i].value},\n\t\t\t`;
      } else if (states[i].type === 'object') {
        code += `${states[i].name}: {\n\t\t\t\t`;
        const { sub = [] } = states[i];
        for (let j = 0; j < sub.length; j++) {
          const subAttr = sub[j];
          if (subAttr.type === 'string') {
            code += `${subAttr.name}: '${subAttr.value}',\n\t\t\t\t`;
          } else if (subAttr.type === 'object') {
            code += `${subAttr.name}: {},\n\t\t\t\t`;
          } else if (subAttr.type === 'array') {
            code += `${subAttr.name}: [],\n\t\t\t\t`;
          } else {
            code += `${subAttr.name}: ${subAttr.value}\n\t\t\t\t`;
          }
        }
        code += '\n\t\t\t},';
      } else if (state[i].type === 'array') {
        code += `${states[i].name}: [],\n\t\t\t`;
      }
    }
    code += '\n\t\t};\n\t}'
    for (let i = 0; i < functions.length; i++) {
      const fun = functions[i];
      code += `\n\t${fun.name} = ${fun.args} => {${fun.content}\n\t}`;
    }

    code += `\n\trender() {\n`;
    code += renderSource;
    code += `\n\t}\n}`;
    return code;
  },
  generateReactComponent(dom, level, {
    target,
    components,
    styles = {},
    functions = [],
    descriptions = {},
  }) {
    if (!dom) {
      return null;
    }
    const doms = dom.childNodes;
    if (doms.length === 0) {
      return null;
    }
    const virtuals = [];
    for (let i = 0; i < doms.length; i++) {
      const $target = $(doms[i]);
      let vdom = null;
      if ($target.hasClass('view-item-box')) {
        const id = $target.attr('id');
        console.log('view-item-box===>', id, $target.attr('data-component'));
        if (id) {
          vdom = components[id];
        } else {
          const componentName = $target.attr('data-component');
          vdom = React.createElement(descriptions[componentName], {});
        }
        let children = null;
        if (Object.prototype.toString.call(vdom.props.children) === '[object String]') {
          children = vdom.props.children;
        } else {
          children = XUE.generateReactComponent(doms[i], level + 1, {
            target,
            components,
            styles,
            functions,
            descriptions,
          });
        }
        const { props } = vdom;
        const targetProps = {
          ...props,
          children,
        };
        const type = vdom.type;
        console.log('vdom type====>', vdom, type);
        let domFlag = '';
        if (typeof type === 'function') {
          let funcName = /^function\s+([a-zA-Z]+[a-zA-Z0-9_]*)\s*\(/.exec(type.toString());
          domFlag = funcName[1].trim();
        } else if (typeof type === 'object') {
          domFlag = type.displayName;
        }
        vdom = React.createElement(descriptions[domFlag], targetProps);
        // console.log('dom flag====>', domFlag, targetProps, vdom, descriptions[domFlag]);
      } else {
        vdom = XUE.generateReactComponent(doms[i], level + 1, {
          target,
          components,
          styles,
          functions,
          descriptions,
        });
        console.log('vdom====>', vdom);
      }
      if (!!vdom) {
        virtuals.push(vdom);
      }
    }
    return virtuals.length > 1 ? virtuals : virtuals.length === 1 ? virtuals[0] : null;
  },
  reactCodeResult(type, level, props = [], children = '') {
    const propsArr = [];
    for (let key in props) {
      if (key === 'children' || key === 'prefixCls') {
        continue;
      }
      if (typeof props[key] === 'function') {
        // TODO: 检测props是否为函数，如果为函数则需要转换为this.on形式
      } else if (Object.prototype.toString.call(props[key]) === '[object Array]') {
        propsArr.push(`${key}={${JSON.stringify(props[key])}`);
      } else if (Object.prototype.toString.call(props[key]) === '[object String]') {
        propsArr.push(`${key}="${props[key]}"`);
      } else if (Object.prototype.toString.call(props[key]) === '[object Number]') {
        propsArr.push(`${key}={${props[key]}}`);
      } else if (Object.prototype.toString.call(props[key]) === '[object Boolean]') {
        propsArr.push(`${key}={${props[key]}}`);
      }
    }
    let domFlag = '';
    if (typeof type === 'function') {
      let funcName = /^function\s+([a-zA-Z]+[a-zA-Z0-9_]*)\s*\(/.exec(type.toString());
      domFlag = funcName[1].trim();
    } else if (typeof type === 'string') {
      domFlag = type;
    } else if (typeof type === 'object') {
      domFlag = type.displayName;
    }
    if (domFlag === '') {
      if (Object.prototype.toString.call(children) === '[object Array]') {
        return children.join('\n');
      } else if (Object.prototype.toString.call(children) === '[object String]') {
        return `${children}`;
      }
      return children;
    }
    let tabs = '\t\t';
    for (let i = 0; i < level; i++) {
      tabs += '\t';
    }
    let childrenCode = children;
    if (Object.prototype.toString.call(children) === '[object Array]') {
      childrenCode = children.join('\n');
    } else if (Object.prototype.toString.call(children) === '[object String]') {
      childrenCode = `${children}`;
    }
    const code = `${tabs}<${domFlag}${propsArr.length === 0 ? '' : propsArr.length === 1 ? ` ${propsArr[0]}` : `\n\t${tabs}${propsArr.join(`\n\t${tabs}`)}\n${tabs}`}>\n${childrenCode}\n${tabs}</${domFlag}>`;
    console.log('code===>', code)
    return code;
  },
  generateReactCode(reactDom, level = 0) {
    if (!reactDom) {
      return null;
    }
    const type = reactDom.type;
    if (!reactDom.props) {
      return XUE.reactCodeResult(type, level);
    }
    if (!!!reactDom.props.children) {
      return XUE.reactCodeResult(type, level, reactDom.props);
    }
    if (Object.prototype.toString.call(reactDom.props.children) === '[object String]') {
      return XUE.reactCodeResult(type, level, reactDom.props, reactDom.props.children);
    }
    if (Object.prototype.toString.call(reactDom.props.children) === '[object Array]') {
      let doms = [];
      for (let i = 0; i < reactDom.props.children.length; i++) {
        const childrenCode = XUE.generateReactCode(reactDom.props.children[i], level + 1);
        doms.push(childrenCode);
      }
      return XUE.reactCodeResult(type, level, reactDom.props, doms);
    }
    return XUE.reactCodeResult(type, level, reactDom.props, XUE.generateReactCode(reactDom.props.children, level + 1));
  },
};

